using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;
using Matrix.ServiceDiscovery.Services;
using StackExchange.Redis;

namespace MatrixServiceDiscovery.HttpApi.Host.HealthChecks;

/// <summary>
/// 服务发现服务健康检查
/// </summary>
public class ServiceDiscoveryHealthCheck : IHealthCheck, ITransientDependency
{
    private readonly ILogger<ServiceDiscoveryHealthCheck> _logger;
    private readonly IUnitOfWorkManager _unitOfWorkManager;
    private readonly Lazy<IServiceInfoRepository> _serviceRepository;
    private readonly Lazy<IDatabase> _redisDatabase;

    public ServiceDiscoveryHealthCheck(
        ILogger<ServiceDiscoveryHealthCheck> logger,
        IUnitOfWorkManager unitOfWorkManager,
        Lazy<IServiceInfoRepository> serviceRepository,
        Lazy<IDatabase> redisDatabase)
    {
        _logger = logger;
        _unitOfWorkManager = unitOfWorkManager;
        _serviceRepository = serviceRepository;
        _redisDatabase = redisDatabase;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        try
        {
            var healthData = new System.Collections.Generic.Dictionary<string, object>();

            // 1. 检查数据库连接
            var dbHealth = await CheckDatabaseHealthAsync();
            healthData["database"] = dbHealth.Item2;

            // 2. 检查Redis连接
            var redisHealth = await CheckRedisHealthAsync();
            healthData["redis"] = redisHealth.Item2;

            // 3. 检查服务注册表状态
            var registryHealth = await CheckServiceRegistryHealthAsync();
            healthData["service_registry"] = registryHealth.Item2;

            // 4. 检查总体健康状态
            var isHealthy = dbHealth.Item1 && redisHealth.Item1 && registryHealth.Item1;

            var status = isHealthy ?
                HealthCheckResult.Healthy("服务发现服务运行正常", healthData) :
                HealthCheckResult.Degraded("服务发现服务部分功能异常", healthData);

            _logger.LogDebug("服务发现服务健康检查完成 - 状态: {Status}", status.Status);
            return status;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "服务发现服务健康检查失败");
            return HealthCheckResult.Unhealthy("服务发现服务异常", ex.Message);
        }
    }

    private async Task<(bool, string)> CheckDatabaseHealthAsync()
    {
        try
        {
            using var uow = _unitOfWorkManager.Begin();
            var count = await _serviceRepository.Value.GetCountAsync();
            await uow.CompleteAsync();

            return (true, $"正常 (服务总数: {count})");
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "数据库连接检查失败");
            return (false, $"异常: {ex.Message}");
        }
    }

    private async Task<(bool, string)> CheckRedisHealthAsync()
    {
        try
        {
            var testKey = "health:check:test";
            var testValue = DateTime.UtcNow.ToString();

            await _redisDatabase.Value.StringSetAsync(testKey, testValue, TimeSpan.FromMinutes(1));
            var retrievedValue = await _redisDatabase.Value.StringGetAsync(testKey);
            await _redisDatabase.Value.KeyDeleteAsync(testKey);

            var isHealthy = retrievedValue == testValue;
            return (isHealthy, isHealthy ? "正常" : "数据不一致");
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Redis连接检查失败");
            return (false, $"异常: {ex.Message}");
        }
    }

    private async Task<(bool, string)> CheckServiceRegistryHealthAsync()
    {
        try
        {
            using var uow = _unitOfWorkManager.Begin();
            var activeServicesCount = await _serviceRepository.Value.CountAsync(x => x.Status == Enums.ServiceStatus.Running);
            var totalServicesCount = await _serviceRepository.Value.GetCountAsync();
            await uow.CompleteAsync();

            if (totalServicesCount == 0)
            {
                return (true, "空注册表 (服务总数: 0)");
            }

            var healthPercentage = (double)activeServicesCount / totalServicesCount * 100;
            var status = healthPercentage >= 80 ? "正常" : healthPercentage >= 50 ? "警告" : "异常";

            return (healthPercentage >= 50, $"活跃服务: {activeServicesCount}/{totalServicesCount} ({healthPercentage:F1}%) - {status}");
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "服务注册表检查失败");
            return (false, $"异常: {ex.Message}");
        }
    }
}